class ChunkUploader {
    constructor(options) {
        this.chunkSize = options.chunkSize || 1024 * 1024; // 默认1MB
        this.concurrent = options.concurrent || 3; // 默认每个文件3个并发上传
        this.uploadUrl = options.uploadUrl; // 分片上传接口
        this.mergeUrl = options.mergeUrl; // 合并接口
        this.onProgress = options.onProgress || function () {};
        this.onComplete = options.onComplete || function () {};
    }


    async uploadFile(file,type) {
        const chunks = this._createChunks(file);
        const fileHash = await this._calculateFileHash(file);

        const uploadTasks = chunks.map((chunk, index) => () => this._uploadChunk(chunk, index, file.name, fileHash, chunks.length));
        await this._runConcurrent(uploadTasks, this.concurrent);

        const result = await this._mergeChunks(file.name, fileHash, chunks.length);
        const filePath = baseUrl + result.filePath;
        this.onComplete(filePath,type);
    }

    _createChunks(file) {
        const chunks = [];
        let start = 0;
        while (start < file.size) {
            const end = Math.min(file.size, start + this.chunkSize);
            chunks.push(file.slice(start, end));
            start = end;
        }
        return chunks;
    }

    async _uploadChunk(chunk, index, fileName, fileHash, totalChunks) {
        const formData = new FormData();
        formData.append("chunk", chunk);
        formData.append("fileName", fileName);
        formData.append("chunkIndex", index);
        formData.append("fileHash", fileHash);
        formData.append("totalChunks", totalChunks);

        await fetch(this.uploadUrl, {
            method: "POST",
            body: formData,
        });

        this.onProgress(fileName, index, totalChunks);
    }

    async _mergeChunks(fileName, fileHash, totalChunks) {
        const response = await fetch(this.mergeUrl, {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({
                fileName,
                fileHash,
                totalChunks,
            }),
        });
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }

        const result = await response.json();
        return result; // 假设服务器返回的JSON中包含filePath字段
    }

    _runConcurrent(tasks, limit) {
        let index = 0;
        let running = 0;

        return new Promise((resolve, reject) => {
            const results = [];
            const runNext = () => {
                if (index === tasks.length && running === 0) {
                    resolve(results);
                    return;
                }

                while (running < limit && index < tasks.length) {
                    const taskIndex = index++;
                    running++;
                    tasks[taskIndex]()
                        .then((res) => {
                            results[taskIndex] = res;
                            running--;
                            runNext();
                        })
                        .catch(reject);
                }
            };
            runNext();
        });
    }

    /**
     * 计算文件哈希
     * @param {File} file 文件对象
     * @returns {Promise<string>} 文件哈希
     */
    async _calculateFileHash(file) {
        return new Promise((resolve) => {
            const chunkSize = 2 * 1024 * 1024; // 2MB chunks for hash calculation
            const chunks = Math.ceil(file.size / chunkSize);
            const spark = new SparkMD5.ArrayBuffer();
            const fileReader = new FileReader();
            let currentChunk = 0;

            fileReader.onload = function(e) {
                spark.append(e.target.result);
                currentChunk++;
                if (currentChunk < chunks) {
                    loadNext();
                } else {
                    resolve(spark.end());
                }
            }.bind(this);

            const loadNext = () => {
                const start = currentChunk * chunkSize;
                const end = Math.min(start + chunkSize, file.size);
                fileReader.readAsArrayBuffer(file.slice(start, end));
            };

            loadNext();
        });
    }
}
